package com.inputabc.ct.v1.listener;

import com.inputabc.ct.v1.context.Components;
import com.inputabc.ct.v1.context.ComponentsBuilder;
import com.inputabc.ct.v1.context.ContextParams;
import com.inputabc.ct.v1.controller.TextContentController;
import com.inputabc.ct.v1.ui.TextBox;
import org.apache.commons.lang.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.util.Map;

/**
 * 剪贴板监控器
 * 负责对剪贴板文本的监控和操作
 * 由于监控需要一个对象作为ClipboardOwner，故不能用静态类
 */
public class SystemClipboardListener implements ClipboardOwner {
    private Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    private Components textBoxComponents = ComponentsBuilder.getComponentsContext().get(TextBox.class);
    private JTextArea jta = (JTextArea) textBoxComponents.get("textBoxTextArea");
    private JScrollPane jsp = (JScrollPane) textBoxComponents.get("textBoxScrollPane");
    private TextContentController tcc = new TextContentController();
    private Map<Object, Object> contextParam = ContextParams.contextParam;

    public SystemClipboardListener() {
        //如果剪贴板中有文本，则将它的ClipboardOwner设为自己
        trySetOwnership(clipboard.getContents(null));
    }


    /**********************************************
     * 如果剪贴板的内容改变，则系统自动调用此方法 *
     **********************************************
     */
    @Override
    public void lostOwnership(Clipboard clipboard, Transferable contents) {

        // 如果不暂停一下，经常会抛出IllegalStateException
        // 猜测是操作系统正在使用系统剪切板，故暂时无法访问
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 取出文本并进行一次文本处理
        String text = tryGetContent();
        if (StringUtils.isNotBlank(text)) {
            String content = null;
            try {
                contextParam.put("sourceContent", text);
                //调用控制器获取翻译后的文本内容
                content = tcc.getTranslatedContent(text);
                if (content == null) {
                    content = "";
                }
                contextParam.put("translatedContent", content);
                Map<Integer, Color> fgColorMap = (Map<Integer, Color>) ContextParams.contextParam.get("fgColorMap");
                int pos = (int) ContextParams.contextParam.get("colorMapPos");
                jta.setForeground(fgColorMap.get(pos));
                jta.setText(content);
            } catch (Exception e) {
                e.printStackTrace();
                if (jsp.getViewport().getBackground().getRGB() == -53971) {
                    jta.setForeground(Color.BLUE);
                } else {
                    jta.setForeground(Color.RED);
                }
                jta.setText("出错了！" + System.lineSeparator() + e.getMessage());
            } finally {
                // 存入剪贴板，并注册自己为所有者
                // 用以监控下一次剪贴板内容变化
                StringSelection tmp = new StringSelection(text);
                trySetOwnership(tmp);
            }
        } else {
            trySetOwnership(clipboard.getContents(null));
        }

    }

    /**
     * 反复尝试获取所有权
     */
    private void trySetOwnership(Transferable transferable) {
        while (true) {
            try {
                clipboard.setContents(transferable, this);
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
            break;
        }
    }

    /**
     * 反复尝试获取剪切板里的文本数据
     *
     * @return
     */
    private String tryGetContent() {
        String text = null;
        while (true) {
            try {
                if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
                    text = (String) clipboard.getData(DataFlavor.stringFlavor);
                }
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return text;
    }
}
